package com.yanzhan.util;

import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author yyb
 * @Description
 * @Date Create in 2018-06-05
 * @Time 13:56
 */
@Component
public class EsClientBuilder {
    private  Logger logger = LoggerFactory.getLogger(getClass());
    private String clusterName;
    private String nodeIpInfo;


    public TransportClient client;

    public String getClusterName() {
        return clusterName;
    }

    private void setClusterName(String clusterName) {
        this.clusterName = clusterName;
    }

    public String getNodeIpInfo() {
        return nodeIpInfo;
    }

    private void setNodeIpInfo(String nodeIpInfo) {
        this.nodeIpInfo = nodeIpInfo;
    }

    public TransportClient getClient() {
        return client;
    }

    private void setClient(TransportClient client) {
        this.client = client;
    }

    /**
     * java连接es注意事项 ：
     * 1.端口号不能与HTTP设置的端口号一致！！！！  例如：HTTP 192.168.116.129:9200  这里需配置为 192.168.116.129:9300，客户端默认端口
     * 2.cluster.name 需与 es/config/elasticsearch.yml配置文件中的cluster.name 一致
     * <p>
     * 否则会报：NoNodeAvailableException
     */
    public EsClientBuilder init() {
        logger.info("------ nodeIpInfo  -------");
        logger.info(nodeIpInfo);
        if(!nodeIpInfo.contains(",")){
            return initOneHost();
        }else {
            return initCluster();
        }
    }

    private EsClientBuilder initOneHost(){
        //设置集群的名字
        TransportAddress transportAddress = null;
        try {
            Settings settings = Settings.builder()
                    .put("cluster.name", clusterName)
                    .build();
            client = new PreBuiltTransportClient(settings);
            transportAddress = new InetSocketTransportAddress(InetAddress.getByName(nodeIpInfo.split(":")[0]), Integer.parseInt(nodeIpInfo.split(":")[1]));
            client.addTransportAddress(transportAddress);
        } catch (Exception e) {
            logger.error("获取服务地址失败，异常信息：{}", e.getMessage());
        }
        if (null == transportAddress) {
            logger.error("获取服务地址失败，服务地址不可用！");
            return null;
        }
        return this;
    }

    private EsClientBuilder initCluster(){
        //创建集群client并添加集群节点地址  集群没测试，大家可自行测试
        Settings settings = Settings.builder()
                .put("client.transport.sniff", false)
                .put("cluster.name", clusterName)
                .build();
        client = new PreBuiltTransportClient(settings);
        Map<String, Integer> nodeMap = parseNodeIpInfo();
        for (Map.Entry<String,Integer> entry : nodeMap.entrySet()){
            try {
                client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(entry.getKey()), entry.getValue()));
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
        logger.debug(this.toString());
        return this;
    }

    // 解析节点IP信息,多个节点用逗号隔开,IP和端口用冒号隔开
    private Map<String, Integer> parseNodeIpInfo() {
        String[] nodeIpInfoArr = nodeIpInfo.split(",");
        Map<String, Integer> map = new HashMap<>(nodeIpInfoArr.length);
        for (String ipInfo : nodeIpInfoArr) {
            String[] ipInfoArr = ipInfo.split(":");
            map.put(ipInfoArr[0], Integer.parseInt(ipInfoArr[1]));
        }
        return map;
    }

    //###  测试
    //根据指定的索引类型文档id  查询;我这里使用的Client 是TransportClient的父类;
    public void searchSingle() {
        logger.info(client.toString());
        GetResponse gResponse = client.prepareGet("test", "tes1", "1")
                .execute()
                .actionGet();
        logger.info("索引 {}", gResponse.getIndex());
        logger.info("类型 {}", gResponse.getType());
        logger.info("版本 {}", gResponse.getVersion());
        logger.info("是否成功 {}", gResponse.isExists());
        Map<String, Object> results = gResponse.getSource();
        if (results != null) {
            for (String key : results.keySet()) {
                Object field = results.get(key);
                System.out.println(key + "\t\t" + field);
            }
        }
    }

    public void close(){
        this.client.close();
    }
}